package com.example.springboot0507.basic.web;


import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.example.springboot0507.basic.annotation.RequestJson;
import com.example.springboot0507.basic.constant.CommonConstants;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Objects;

/**
 * 自定义JSON参数解析
 * @create: 2019-09-02 09:54
 */
@Component
public class RequestJsonHandler implements HandlerMethodArgumentResolver {

    /**
     * 拦截方法参数限制  只有被RequestJson注解标记的参数才能进入
     * @param parameter
     * @return
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(RequestJson.class);
    }

    /**
     * 解析参数
     * @param parameter
     * @param mavContainer
     * @param webRequest
     * @param binderFactory
     * @return
     * @throws Exception
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory){
        HttpServletRequest request = WebUtils.getRequest();
        if(!StrUtil.containsIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) return null;
        Object obj =  request.getAttribute(CommonConstants.REQUEST_BODY_DATA);
        synchronized (RequestJsonHandler.class){
            if(Objects.isNull(obj)){
                Map<String, Object> param = WebUtils.getRequestJsonParam();
                request.setAttribute(CommonConstants.REQUEST_BODY_DATA, param);
                obj = param;
            }
        }
        RequestJson requestJson = parameter.getParameterAnnotation(RequestJson.class);
        String fieldName = requestJson.value();
        fieldName = StrUtil.isBlank(fieldName)?parameter.getParameterName():fieldName;
        Object fieldValue = null;
        if(obj instanceof Map && ((Map) obj).containsKey(fieldName)) {
            fieldValue = ((Map) obj).getOrDefault(fieldName, requestJson.defaultValue());
        }
        if (JSONUtil.isNull(fieldValue)) {
            return null;
        }

        Class<?> parameterType = parameter.getParameterType();

        return Convert.convert(parameterType, fieldValue);
    }
}
